import jwt
import datetime
import hmac
import hashlib
import time
import base64
from  config import JWT,API
import traceback
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.hmac import HMAC
from cryptography.hazmat.backends import default_backend

''' create a  signature '''
async def generateSignature(secretKey: str, params: dict, timestampMs: int) -> str:
    sortedParams = ""
    if params is not None and (not isinstance(params, dict) or params): # make sure the list is not empty
        sortedParams = "&".join([f"{key}={params[key]}" for key in sorted(params)])
        dataToSign = f"{sortedParams}&timestamp={timestampMs}"
    else:
        dataToSign = f"timestamp={timestampMs}"
    print("dataToSign    ::::    ",dataToSign)
    print('timestampMs    ::::    ',timestampMs)
    signature = hmac.new(secretKey.encode('utf-8'), dataToSign.encode('utf-8'), hashlib.sha256).digest()
    return base64.b64encode(signature).decode()

''' verify a signature   '''
async def verifySignature(secretKey: str, params: dict, timestampMs: int, signature: str) -> bool:
    currentTimestampMs = int(time.time() * 1000)
    if abs(currentTimestampMs - timestampMs) > API['SIGNATURE_EXPIRE_TIME']: # 30000 millionseconds
        print('signature expired')
        return False
    computedSignature = await generateSignature(secretKey, params, timestampMs)
    print('computedSignature     ::::    ',computedSignature )
    res = hmac.compare_digest(computedSignature, signature)
    return res

''' verify a API request signature  '''
async def verifyRequestSignature(reqBody : list , headers : list,secretKey = API['REQUEST_SIGNATURE_KEY'] ) -> bool:
    try:
        signature   = headers.get('X-Signature')
        print('signature    ::::    ',signature)  
        timestampMs = headers.get('X-Timestamp')  
        if not signature or not timestampMs:
            print('headers is invalid!')
            return False
        timestampMs = int(timestampMs)
        isSignatureValid = await verifySignature(secretKey, reqBody, timestampMs, signature)
        return isSignatureValid

    except Exception as e:
        stack_trace = traceback.format_exc()
        print(f"EXCEPTION : utils : auth : verifyRequestSignature  : {str(e)}\n{stack_trace}")
        return False

